/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package univalle.eisc.pais.ai.searcheslab.model;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import univalle.eisc.pais.ai.searcheslab.logic.Seeker;

/**
 *
 * @author victor
 */
public class AStarNode extends Node {

    private int heuristic;
    private List<AStarNode> offsprings;

    public AStarNode(int x, int y) {
        super(x, y);
        this.heuristic = H();
    }

    public AStarNode(Node parent, int x, int y, char operator) {
        super(parent, x, y, operator);
        this.heuristic = H();
    }

    private int H() {
        double d1 = 0.0, d2 = 0.0, d3 = 0.0, d4 = 0.0;
        if (!Seeker.item1Right) {
            if (!Seeker.haveItem1) {
                d1 = distanceTo(Seeker.stage.getItem1());
            } else {
                d2 = distanceTo(Seeker.stage.getPlace1());
            }
        }
        if (!Seeker.item2Right) {
            if (!Seeker.haveItem2) {
                d3 = distanceTo(Seeker.stage.getItem2());
            } else {
                d4 = distanceTo(Seeker.stage.getPlace2());
            }
        }

        return (int) Math.min(d1 + d2, d3 + d4);
    }

    private double distanceTo(VisibleObject ov) {

        return Math.sqrt(Math.pow(this.x - ov.getX(), 2) + Math.pow(this.y - ov.getY(), 2));
    }

    public List<AStarNode> getAStarOffsprings() {
        if (offsprings == null) {
            offsprings = new ArrayList<AStarNode>();
            offsprings.add(getUp());
            offsprings.add(getRight());
            offsprings.add(getDown());
            offsprings.add(getLeft());
            offsprings.removeAll(Collections.singleton(null)); //remove null nodes
        }
        return offsprings;
    }

    @Override
    public AStarNode getUp() {
        if (this.y != 0) {
            AStarNode child = new AStarNode(this, this.x, this.y - 1, 'u');
            if (!child.equals(this.parent)) {
                return child;
            }
        }
        return null;
    }

    @Override
    public AStarNode getDown() {
        if (this.y != Seeker.stage.getConfig().getN() - 1) {
            AStarNode child = new AStarNode(this, this.x, this.y + 1, 'd');
            if (!child.equals(this.parent)) {
                return child;
            }
        }
        return null;
    }

    @Override
    public AStarNode getLeft() {
        if (this.x != 0) {
            AStarNode child = new AStarNode(this, this.x - 1, this.y, 'l');
            if (!child.equals(this.parent)) {
                return child;
            }
        }
        return null;
    }

    @Override
    public AStarNode getRight() {
        if (this.x != Seeker.stage.getConfig().getN() - 1) {
            AStarNode child = new AStarNode(this, this.x + 1, this.y, 'r');
            if (!child.equals(this.parent)) {
                return child;
            }
        }
        return null;
    }

    @Override
    public int compareTo(Node o) {
        if (o == null) {
            return -1;
        }
        int v1 = this.getCost() + this.getHeuristic();
        int v2 = o.getCost() + ((AStarNode) o).getHeuristic();
        return (v1 < v2 ? -1 : (v1 == v2 ? 0 : 1));
    }

    public int getHeuristic() {
        return heuristic;
    }

    public void setHeuristic(int heuristic) {
        this.heuristic = heuristic;
    }
}
